package org.jaronsource.framework.plugins.aop;

import java.io.File;
import java.io.IOException;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.lucene.analysis.Analyzer;
import org.apache.lucene.document.Document;
import org.apache.lucene.document.Field;
import org.apache.lucene.index.IndexWriter;
import org.apache.lucene.index.IndexWriterConfig;
import org.apache.lucene.search.BooleanQuery;
import org.apache.lucene.store.Directory;
import org.apache.lucene.store.NIOFSDirectory;
import org.apache.lucene.util.Version;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Aspect;
import org.jaronsource.framework.plugins.search.IndexDocumentUtils;
import org.jaronsource.framework.plugins.search.SearchUtils;
import org.jaronsource.framework.plugins.search.SearchableBean;
import org.jaronsource.framework.util.StringUtils;
import org.springframework.stereotype.Component;

@Aspect
@Component
public class SearchIndexAdvice {

	private static final String METHODNAME_TO_INTERCEPT = "save";

	private static final Log logger = LogFactory.getLog( SearchIndexAdvice.class );

	@After ( "target(org.jaronsource.framework.core.service.IService)")
	public void index( JoinPoint joinPoint ) {
		String methodName = joinPoint.getSignature().getName();
		Object[] args = joinPoint.getArgs();

		if ( !StringUtils.isBlank( methodName ) && METHODNAME_TO_INTERCEPT.equals( methodName )
		// && args.length == 1
		&& args[0] != null ) {
			Object bean = args[0];

			Class<?> clzss = bean.getClass();
			SearchableBean searchableBean = clzss.getAnnotation( SearchableBean.class );
			if ( searchableBean == null ) { return; }

			IndexWriter indexWriter = null;
			IndexWriterConfig indexWriterConfig = null;
			Directory indexDirectory = null;

			try {

				Document doc = IndexDocumentUtils.createDocument( bean );
				if ( doc != null ) {
					File indexDir = SearchUtils.getIndexDir();
					// 实例化IKAnalyzer分词器
					Analyzer analyzer = SearchUtils.analyzer();
					indexDirectory = new NIOFSDirectory( indexDir );
					// TODO 这里需要根据缓存进行操作,不需要每次实例化!
					// try {
					// SearchUtils.unlock(indexDirectory);
					// } catch (Exception e) {
					// logger.error("", e);
					// }
					indexWriterConfig = new IndexWriterConfig( Version.LUCENE_36, analyzer );
					indexWriter = new IndexWriter( indexDirectory, indexWriterConfig );

					// 删除索引
					if ( searchableBean.removeable() ) {
						removeIndex( bean, clzss, indexWriter );
					}

					// 创建类的类名称索引
					Field field = IndexDocumentUtils.createClassField( bean.getClass() );
					doc.add( field );

					logger.debug( String.format( "%s was indexed.", bean.getClass().toString() ) );
					indexWriter.addDocument( doc );
					indexWriter.commit();
				}

			}
			catch ( Exception e ) {
				logger.warn( String.format( "Could not index %s.", bean.getClass().toString() ), e );
			}
			finally {
				if ( indexWriter != null ) try {
					indexWriter.close();
				}
				catch ( Exception e ) {
					logger.error( "", e );
				}
				if ( indexDirectory != null ) try {
					indexDirectory.close();
				}
				catch ( IOException e ) {
					logger.error( "", e );
				}
			}

		}

	}

	private void removeIndex(	Object bean,
								Class<?> clzss,
								IndexWriter indexWriter ) {

		BooleanQuery pkquery = SearchUtils.makePKQuery( bean );
		if ( pkquery != null ) {
			SearchUtils.deleteDocuments( indexWriter, pkquery, clzss );
		}
	}

}
